#include <memory>


#include "plc2llvm/ScopeSystem/ScopeManager.h"
#include "plc2llvm/ObjectSystem/Object.h"
#include "plc2llvm/TypeSystem/Basic/BasicInclude.h"

using namespace std;
using namespace plcst;

void creatAllBasicType() {
    auto globScope = plcst::ScopeManager::getScopeManager().getGlobalScope();

    #define makeBasicType(tk) new plcst::tk##Type(#tk)

    #define CREATE_INTEGER_AND_INSERT(x) \
        auto x##ty = makeBasicType(x); \
        std::shared_ptr<plcst::Type> shared_##x##ty(x##ty); \
        globScope->insert(std::move(shared_##x##ty)); 

    CREATE_INTEGER_AND_INSERT(INT);

    #undef CREATE_INTEGER_AND_INSERT
    #undef makeBasicType
}

void func(){
        // add new scope
    auto globScope = ScopeManager::getScopeManager().getGlobalScope();
    auto newScope = make_unique<Scope>(globScope);
    auto newScopeptr = newScope.get();
    ScopeManager::getScopeManager().addNewScope(std::move(newScope));

    // add new object to new scope
    auto newObj = std::make_shared<Object>(make_shared<INTType>("INT", 100), "a");
    auto newObjPtr = newObj.get();
    newScopeptr->insert<Object>(std::move(newObj));

    // // add another obj to new scope
    auto t = ScopeManager::getScopeManager().find<Type>("INT");
    shared_ptr<Type> ty_shared(t);
    cerr << ty_shared.use_count() << std::endl;
    auto newObj2 = std::make_unique<Object>(ty_shared, "abc");
    newScopeptr->insert<Object>(move(newObj2));

    // find 
    auto res = ScopeManager::getScopeManager().find<Object>("a");
    auto res1 = ScopeManager::getScopeManager().find<Object>("a");
    assert(res1 == res);
}

class test {
public:
    shared_ptr<int> st;
    test(shared_ptr<int> st) {
        this->st = move(st);
        cout << "create: " <<  this->st.use_count() << endl;
    }
    ~test() {
        cout << "delete: " <<  this->st.use_count() << endl;
    }
};

int main(){
    // creatAllBasicType();
    // func();
    //     // delete
    // ScopeManager::getScopeManager().deleteCurrentScope();
    auto si = make_shared<int>(123);
    shared_ptr<int>& refsi = si;
    auto tp = new test(si);
    cout << "main: before del:" <<  si.use_count() << endl;
    delete tp;
    cout << "main: after del:" <<  si.use_count() << endl;
    return 0;
}